/**
  * @file    NM25Q128_Config.h
  * @brief   NM25Q128 (16MB) SPI 硬件抽象层配置头文件
  *         该文件定义了NM25Q128 Flash芯片的硬件抽象层接口和数据结构
  * @author  18408107475@163.com
  * @version V2.0.0
  *         版本变更记录：
  *         V1.0.0 初始版本
  *         V2.0.0 增加四线SPI模式支持
  * @date    2025-05-24
  */
 
#ifndef __NM25Q128_CONFIG_H
#define __NM25Q128_CONFIG_H

#ifdef __cplusplus
 extern "C" {
#endif

/* 硬件依赖头文件 ----------------------------------------------------------*/
#include "stm32f10x.h"          // STM32标准外设库，提供寄存器定义
#include "SPI2_Config.h"        // SPI2接口硬件配置
#include "NM25Q128_Ins.h"       // NM25Q128指令集定义
#include "USART1_Config.h"      // 调试用串口配置
#include "stdbool.h"            // 提供bool类型支持
#include "Delay.h"              // 精确延时函数

/* 类型定义 ----------------------------------------------------------------*/
/**
  * @brief  JEDEC ID结构体
  * @note   用于存储从Flash读取的JEDEC标准ID
  *         典型值：Manufacturer_ID=0x20(美光)，Device_ID=0x4018(16MB容量)
  */
typedef struct {
    u8  Manufacturer_ID;  // 制造商ID，1字节
    u16 Device_ID;         // 设备ID，2字节
} JEDEC_ID_t;

/**
  * @brief  SPI通信模式枚举
  * @note   定义芯片支持的三种SPI接口模式：
  *         - 标准SPI：单线输入输出
  *         - 双线模式：提高数据传输速率
  *         - 四线模式：最大程度提升性能
  */
typedef enum {
    SPI_MODE_STANDARD = 0,  // 标准SPI模式(仅使用MOSI和MISO)
    SPI_MODE_DUAL,          // 双线模式(双向数据线)
    SPI_MODE_QUAD           // 四线模式(使用IO0-IO3四条数据线)
} SPIMode_TypeDef;

/* 函数声明 ----------------------------------------------------------------*/
/**
  * @brief  读取芯片JEDEC ID
  * @param  ID: 指向JEDEC_ID_t结构体的指针，用于存储读取到的ID
  * @retval 无
  * @note   该函数会发送0x9F指令并读取3字节ID数据
  */
void NM25Q128_ReadID(JEDEC_ID_t *ID);

/**
  * @brief  初始化NM25Q128芯片
  * @retval 初始化状态：
  *         0 - 成功
  *         1 - ID验证失败
  *         2 - 复位失败
  * @note   执行硬件复位序列并验证芯片ID
  */
u8 NM25Q128_Init(void);

/**
  * @brief  写使能
  * @retval 无
  * @note   发送0x06指令设置WEL位，必须在所有编程/擦除操作前调用
  */
void NM25Q128_WriteEnable(void);

/**
  ******************************************************************************
  * @brief  写失能控制
  * @note   关键操作：
  *         - 当处于自定时的页面编程周期时，WIP位为1；周期完成后，WIP位变为0。
  ******************************************************************************
  */
void NM25Q128_WriteDisable(void);

/**
  * @brief  读取状态寄存器
  * @param  reg: 寄存器编号
  *             1 - 状态寄存器1(WIP/WEL/BP位)
  *             2 - 状态寄存器2(QE/SR保护位)
  * @retval 状态寄存器值
  */
u8 NM25Q128_ReadStatus(u8 reg);

/**
  * @brief  检查芯片是否忙
  * @retval 忙状态：
  *         1 - 芯片正忙(执行编程/擦除操作)
  *         0 - 芯片就绪
  * @note   通过检查状态寄存器1的WIP位实现
  */
u8 NM25Q128_IsBusy(void);

/**
  * @brief  擦除4KB扇区
  * @param  Sector_Address: 要擦除的扇区地址(必须4KB对齐)
  * @retval 操作状态：
  *         0 - 成功
  *         1 - 写使能失败
  *         2 - 擦除超时
  * @note   典型擦除时间25ms，最大400ms
  */
u8 NM25Q128_SectorErase(u32 Sector_Address);

/**
  * @brief  页编程(最大256字节)
  * @param  Write_Address: 写入起始地址
  * @param  Data_tBuffer: 要写入的数据缓冲区
  * @param  NumByteToWrite: 要写入的字节数(1-256)
  * @retval 操作状态：
  *         0 - 成功
  *         1 - 写入失败
  * @note   会自动处理页边界回卷，典型编程时间0.7ms/256字节
  */
u8 NM25Q128_WritePage(u32 Write_Address, u8 *Data_tBuffer, u16 NumByteToWrite);

/**
  * @brief  读取数据
  * @param  Read_Address: 读取起始地址
  * @param  rData_pBuffer: 数据存储缓冲区
  * @param  NumByteToRead: 要读取的字节数
  * @retval 操作状态：
  *         0 - 成功
  *         1 - 读取失败
  * @note   使用标准读指令(0x03)，时钟速率≤50MHz
  */
u8 NM25Q128_ReadData(u32 Read_Address, u8 *rData_pBuffer, u16 NumByteToRead);

/**
  * @brief  进入深度掉电模式
  * @retval 无
  * @note   发送0xB9指令，将功耗降至最低(约5μA)
  *         唤醒需要发送0xAB指令并等待30μs
  */
void NM25Q128_Sleep(void);

#ifdef __cplusplus
}
#endif

#endif /* __NM25Q128_CONFIG_H */
